package x2rel.qMap.core;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Random;
import x2rel.qMap.logger.Logging;

public class VariablesHandler extends XmlHandler {

    private ArrayList<Variables> vars;
    private ArrayList<Variables> temp;

    public VariablesHandler() {
        this.vars = new ArrayList<Variables>();
        this.temp = null;
    }

    public ArrayList<Variables> processVarList(ArrayList<Variables> temp) {


        this.temp = temp;

        //Logging.getInstance().log("TEMP Node:\n\n" + dump(temp), 3);        


        // Search by "For"
        ArrayList<Variables> vfor = getVarByName(temp, "For");

        if (vfor != null && !vfor.isEmpty()) {
            for (Variables v : vfor) {
                Logging.getInstance().log("For Node:\n\n" + dump(v), 3);
                Variables t = new Variables();
                t = getForValues(v, t);
                this.vars.add(t);
            }
        }

        // Search by "Return"
        ArrayList<Variables> vret = getVarByName(temp, "Return");

        if (vret != null && !vret.isEmpty()) {
            for (Variables v : vret) {
                Logging.getInstance().log("Return Node:\n\n" + dump(v), 3);
                Variables t = new Variables();
                t = getReturnValues(v, t);
                this.vars.add(t);
            }
        }

        // Search by "Return"
        ArrayList<Variables> vwhere = getVarByName(temp, "Where");
        
        if (vwhere != null && !vwhere.isEmpty()) {
            for (Variables v : vwhere) {
                Logging.getInstance().log("Where Node:\n\n" + dump(v), 3);
                Variables t = new Variables();

                t = getWhereValues(v, t);

                this.vars.add(t);
            }
        }

        return this.vars;
    }

    private ArrayList<Variables> getVarByName(ArrayList<Variables> list, String name) {
        return getVarByName(list, name, 0);
    }

    private ArrayList<Variables> getVarByName(ArrayList<Variables> list, String name, Integer tipo) { // tipo = 1 : procura em referencias
        boolean exist = false;
        ArrayList<Variables> retorno = new ArrayList<Variables>();

        for (int i = 0; i < list.size(); i++) {
            if (tipo == 1 ? list.get(i).getReference().equalsIgnoreCase(name) : list.get(i).getName().equalsIgnoreCase(name)) {
                retorno.add(list.get(i));
                exist = true;
            }
        }

        if (exist) {
            return retorno;
        } else {
            for (int i = 0; i < list.size(); i++) {
                if (tipo == 1 ? list.get(i).getReference().contains(name) : list.get(i).getName().contains(name.trim())) {
                    retorno.add(list.get(i));
                    exist = true;
                }
            }
            if (exist) {
                return retorno;
            } else {
                return null;
            }
        }
    }

    private String getValue(Variables v) {
        if (!v.getValue().isEmpty()) {
            return v.getValue();
        } else if (v.getVarValue() != null) {
            return getValue(v.getVarValue());
        } else {
            return "";
        }
    }

    private Variables getForValues(Variables v, Variables For) {

        Variables ref = null;
        Variables val = null;
        Variables var = new Variables();
        //Logging.getInstance().log("v:\n" + v.toString(), 3);

        if (v.getName().equalsIgnoreCase("For")) {
            For.setName("For");

            if (v.getVarRef() != null) {

                if (v.getVarRef().getName().equalsIgnoreCase("Param")) {
                    For.setReference(v.getVarRef().getValue());
                }

                //@TODO verificar outras possibilidades

            }

            if (v.getVarValue() != null) {
                getForValues(v.getVarValue(), For);
            }

        }
        if (v.getName().startsWith("#")) {
            For.setXpath(For.getXpath() + v.getValue());
        }
        if (v.getName().equalsIgnoreCase("Map")) {

            if (v.getVarRef() != null) {
                if (v.getVarRef().getName().equalsIgnoreCase("param")) {
                    String[] values = v.getVarRef().getValue().trim().split(":");
                    //ArrayList<Variables> vs = getVarByName(this.temp, values[1]);                    
                    if (For.getXpath().isEmpty()) {
                        For.setXpath(getVarByName(this.temp, values[1]).get(0).getValue());
                    } else {
                        For.setXpath(getVarByName(this.temp, values[1]).get(0).getValue() + For.getXpath());
                    }
                }
            }
            if (v.getVarValue() != null) {
                if (v.getVarValue().getName().equalsIgnoreCase("Parse")) {
                    For.setDocument(v.getVarValue().getValue());
                } else {
                    if (countStr(v.getVarValue().getValue(), ":") == 3) {
                        String[] values = v.getVarValue().getValue().trim().split(":");

                        Variables f = getVarByName(this.vars, values[3], 1).get(0);

                        if (For.getXpath().isEmpty()) {
                            For.setXpath(f.getXpath());
                        } else {
                            For.setXpath(f.getXpath() + For.getXpath());
                        }

                        For.setDocument(f.getDocument());

                        getForValues(v.getVarRef(), For);

                    } else {
                        getForValues(v.getVarValue(), For);
                    }
                }
            }


        }
        return For;

    }

    private Variables getReturnValues(Variables v, Variables Ret) {

        if (v.getName().equalsIgnoreCase("Return")) {
            Ret.setName("Return");

            if (v.getVarValue() == null && v.getVarRef() == null) {
                String[] values = v.getValue().trim().split(":");
                Variables r = getVarByName(this.vars, values[1], 1).get(0);
                Ret.setDocument(r.getDocument());
                Ret.setXpath(r.getXpath());
                return Ret;
            }

            if (v.getVarRef() != null) {
                // not used
            }

            if (v.getVarValue() != null) {
                getReturnValues(v.getVarValue(), Ret);
            }

        }

        if (v.getName().startsWith("#")) {

            Ret.setXpath(Ret.getXpath() + (v.getValue().startsWith("@") ? v.getValue().replace("@", "/") : v.getValue()));
        }

        if (v.getName().equalsIgnoreCase("Map")) {

            if (v.getVarRef() != null) {
                if (v.getVarRef().getName().equalsIgnoreCase("param")) {
                    String[] values = v.getVarRef().getValue().trim().split(":");
                    String xpath = getVarByName(this.temp, values[1]).get(0).getValue();
                    xpath = xpath.startsWith("@") ? xpath.replace("@", "/") : xpath;

                    if (!xpath.equalsIgnoreCase("/text()")) {
                        if (Ret.getXpath().isEmpty()) {
                            Ret.setXpath(xpath);
                        } else {
                            Ret.setXpath(xpath + Ret.getXpath());
                        }
                    }
                }
            }
            if (v.getVarValue().getName().equalsIgnoreCase("Parse")) {
                Ret.setDocument(v.getVarValue().getValue());
            } else {

                if (v.getVarValue() != null) {
                    if (countStr(v.getVarValue().getValue(), ":") == 3) {
                        String[] values = v.getVarValue().getValue().trim().split(":");

                        Variables f = getVarByName(this.vars, values[3], 1).get(0);

                        if (Ret.getXpath().isEmpty()) {
                            Ret.setXpath(f.getXpath());
                        } else {
                            Ret.setXpath(f.getXpath() + Ret.getXpath());
                        }

                        Ret.setDocument(f.getDocument());

                        getReturnValues(v.getVarRef(), Ret);

                    } else {
                        getReturnValues(v.getVarValue(), Ret);
                    }

                }
            }


        }
        return Ret;
    }

    private Variables getWhereValues(Variables v, Variables Where) {


        if (v.getName().equalsIgnoreCase("Where")) {
            Where.setName("Where");
            Random rn = new Random();
            Where.setCod(rn.nextInt()+1);

            Where.setWhere_op(v.getWhere_op());


            /*
             * satisfies op:string-equal
             * satisfies op:gt
             * satisfies op:double-lt
             * satisfies op:double-gt
             * 
             */
            String[] values = v.getWhere().trim().split(":");
            String w = values[1];
            if (w.equalsIgnoreCase("string-equal")) {
                Where.setWhere("=");
            }
            if (w.equalsIgnoreCase("gt") || w.equalsIgnoreCase("double-gt")) {
                Where.setWhere(">");
            }
            if (w.equalsIgnoreCase("lt") || w.equalsIgnoreCase("double-lt")) {
                Where.setWhere("<");
            }


            /*
             * satisfies some $fs: v_5 in 1991;
             * satisfies some $fs:v_3 in 'Addison-Wesley'
             * satisfies some $fs:v_3 in 'Fantasy'
             * satisfies some $fs:v_5 in 10
             * satisfies some $fs:v_7 in 2000
             * satisfies some $fs:v_3 in 'Corets, Eva'
             * satisfies some $fs:v_3 in 'Tim'
             * 
             */
            String[] values2 = v.getValue().split(" in ");
            Where.setValue(values2[1]);



            if (v.getVarValue() != null) {
                getWhereValues(v.getVarValue(), Where);
            }

        }
        if (v.getName().startsWith("#")) {
            if (v.getValue().startsWith("@")) {
                Where.setXpath(Where.getXpath() + v.getValue().replace("@", "/"));
            } else {
                Where.setXpath(Where.getXpath() + v.getValue());
            }
        }
        if (v.getName().equalsIgnoreCase("Map")) {

            if (v.getVarRef() != null) {
                if (v.getVarRef().getName().equalsIgnoreCase("param")) {
                    String[] values = v.getVarRef().getValue().trim().split(":");
                    String xpath = getVarByName(this.temp, values[1]).get(0).getValue();
                    xpath = xpath.startsWith("@") ? xpath.replace("@", "/") : xpath;

                    if (!xpath.equalsIgnoreCase("/text()")) {
                        if (Where.getXpath().isEmpty()) {
                            Where.setXpath(xpath);
                        } else {
                            Where.setXpath(xpath + Where.getXpath());
                        }
                    }
                }
            }
            if (v.getVarValue().getName().equalsIgnoreCase("Parse")) {
                Where.setDocument(v.getVarValue().getValue());
            } else {

                if (v.getVarValue() != null) {
                    if (countStr(v.getVarValue().getValue(), ":") == 3) {
                        String[] values = v.getVarValue().getValue().trim().split(":");

                        Variables f = getVarByName(this.vars, values[3], 1).get(0);

                        if (Where.getXpath().isEmpty()) {
                            Where.setXpath(f.getXpath());
                        } else {
                            Where.setXpath(f.getXpath() + Where.getXpath());
                        }

                        Where.setDocument(f.getDocument());

                        getWhereValues(v.getVarRef(), Where);

                    } else {
                        getWhereValues(v.getVarValue(), Where);
                    }

                }
            }


        }
        return Where;
    }
}
